<template>
  <div
    v-if="list.length"
    :class="{'wrapper': true, 'wrapper--scroll': isHover}"
    @mouseenter="handleFn"
    @mouseleave="handleFn">
    <!-- img wrap -->
    <div class="list-wrapper" :style="`transform: translateX(-${moveX}px)`">
      <slot
        v-for="item in itemList"
        name="content"
        :data="item">
      </slot>
    </div>
    <!-- scroll bar -->
    <div
      ref="scrollBar"
      class="scroll-bar"
      :style="{'visibility': isHover ? 'visible' : 'hidden'}"
      @click="handleBarClick">
      <div
        ref="scrollPoint"
        class="scroll-point"
        :style="`transform: translateX(${scrollMoveX}px)`"
        @mousedown="handleMouseDown"
        @mousemove="handleMouseMove"
        @mouseup="handleMouseLeave"
        @mouseleave="handleMouseLeave">
      </div>
    </div>
  </div>
</template>
<script>
/**
 * @file 多图轮播
 */
export default {
  name: 'MultipleCarousel',
  props: {
    list: {
      type: Array,
      default: () => []
    },
    // 轮播间隔
    interval: {
      type: Number,
      default: 20
    },
    // 一行最多展示几个
    max: {
      type: Number,
      default: 3
    },
    // 条目宽度
    itemWidth: {
      type: Number,
      default: 300
    },
    // 条目间隔
    itemSpacing: {
      type: Number,
      default: 20
    }
  },
  data() {
    return {
      // 盒子移动距离
      moveX: 0,
      // 定时器
      timer: null,
      // 是否hover
      isHover: false,
      // 滚动滑块移动距离
      scrollMoveX: 0,
      // 拖动滑块起始位置,
      startX: 0,
      // 是否在拖动滑块,
      dragFlag: false,
      // 滚动条和滑块之间的偏移量
      offset: 0
    }
  },
  computed: {
    itemList() {
      if (this.list.length <= this.max) {
        return this.list
      } else {
        return [...this.list, ...this.list]
      }
    },
    // 最大轮播距离
    maxMoveX() {
      return this.list.length * (this.itemWidth + this.itemSpacing)
    },
    // 滑块可移动的最大距离
    barMaxMoveX() {
      const barWidth = this.$refs.scrollBar.clientWidth
      const pointWidth = this.$refs.scrollPoint.clientWidth
      return barWidth - pointWidth
    }
  },
  watch: {
    moveX(nVal) {
      if (nVal >= this.maxMoveX) {
        this.moveX = 0
        this.moveX++
      }
    },
    isHover(nVal) {
      if (nVal) {
        this.scrollMoveX = this.moveX * this.barMaxMoveX / this.maxMoveX
      }
    }
  },
  mounted() {
    if (this.list.length <= this.max) {
      return
    }
    this.play()
  },
  beforeDestroy() {
    this.stop()
    this.timer = null
  },
  methods: {
    play() {
      this.timer = setInterval(() => {
        this.moveX++
      }, this.interval)
    },
    stop() {
      clearInterval(this.timer)
    },
    handleFn(e) {
      if (this.list.length <= this.max) {
        return
      }
      if (e.type === 'mouseenter') {
        this.isHover = true
        this.stop()
      } else {
        this.isHover = false
        this.play()
      }
    },
    // 按下鼠标时，记录鼠标初始位置，滑块和滚动条之间的偏移量
    handleMouseDown(e) {
      e.preventDefault()
      this.dragFlag = true
      this.startX = e.clientX
      const barOffsetX = this.$refs.scrollBar.getBoundingClientRect().left
      const pointOffsetX = this.$refs.scrollPoint.getBoundingClientRect().left
      this.offset = pointOffsetX - barOffsetX
    },
    handleMouseMove(e) {
      if (this.dragFlag) {
        // 滑块移动距离 = 鼠标移动距离 + 滑块相对背景条的偏移量
        this.scrollMoveX = e.clientX - this.startX + this.offset
        if (this.scrollMoveX <= 0) {
          this.scrollMoveX = 0
        }
        if (this.scrollMoveX >= this.barMaxMoveX) {
          this.scrollMoveX = this.barMaxMoveX
        }
        this.moveX = this.scrollMoveX * this.maxMoveX / this.barMaxMoveX
      }
    },
    handleMouseLeave() {
      this.dragFlag = false
    },
    handleBarClick() {
      const pointWidth = this.$refs.scrollPoint.clientWidth
      const pointOffsetX = this.$refs.scrollPoint.getBoundingClientRect().left
      this.scrollMoveX += e.clientX - pointOffsetX - pointWidth / 2
      this.moveX = this.scrollMoveX * this.maxMoveX / this.barMaxMoveX
    }
  }
}
</script>

<style lang="less" scoped>
.wrapper {
  overflow: hidden;
  position: relative;
  user-select: none;
  height: 100%;

  .list-wrapper {
    display: flex;
  }

  .scroll-bar {
    position: absolute;
    background: #ededed;
    border-radius: 4px;
    bottom: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 50%;
    height: 8px;
    cursor: pointer;

    .scroll-point {
      position: absolute;
      width: 64px;
      height: 8px;
      background: #b0bcc9;
      border-radius: 4px;
      top: 50%;
      margin-top: -4px;
      cursor: pointer;
    }
  }
}
</style>
